import json
import re
from meiduo_mall.utils.sinaweibopy3 import APIClient
from QQLoginTool.QQtool import OAuthQQ
from django import http
from django.conf import settings
from django.contrib.auth import login
from django.shortcuts import render, redirect
from django_redis import get_redis_connection

from carts.utils import merge_cookie_redis_cart

from .models import OAuthQQUser, OAuthSinaUser
from oatuh.utils import decode_sign_openid

# Create your views here.
from django.views import View
from users.models import User


class OAuthQQLoginView(View):
    # 获取参数
    def get(self,request):
        state = request.GET.get('next','/')

        # 创建Ooauth对象
        oauth_qq = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                            client_secret=settings.QQ_CLIENT_SECRET,
                            redirect_uri=settings.QQ_REDIRECT_URI,
                            state=state)
        # 获取qq登录页面
        login_url = oauth_qq.get_qq_url()
        print(login_url)
        # 返回响应
        return http.JsonResponse({"login_url":login_url})
class OAuthUserView(View):
    # 获取参数
    def get(self,request):
        # 1， 获取code
        state = request.GET.get('state')
        code = request.GET.get('code')

        # 判空
        if not code:
            return http.HttpResponseForbidden('code失效')

        # 创建oauth对象
        oauth_qq = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                            client_secret=settings.QQ_CLIENT_SECRET,
                            redirect_uri=settings.QQ_REDIRECT_URI,
                            state=state)

        # 获取access_token
        access_token = oauth_qq.get_access_token(code)

        # 获取openid
        openid = oauth_qq.get_open_id(access_token)
        # print('1--',openid)
        # 获取openid的关联用户
        try:
            oauth_qq_user = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 初次授权
            # 将openid加密，并返回到页面渲染
            from oatuh.utils import generate_sign_openid
            sign_openid = generate_sign_openid(openid)
            # print('2--',sign_openid)
            return render(request,'oauth_callback.html',context={'token':sign_openid})
        # 非初次授权
        user = oauth_qq_user.user

        # 状态保持
        login(request, user)
        request.session.set_expiry(3600*24*2)

        # 返回响应
        response = redirect('/')
        response.set_cookie('username', user.username)

        #合并购物车
        response = merge_cookie_redis_cart(user, request, response)
        return response

    def post(self,request):
        sign_openid = request.POST.get('access_token')
        # 前端逻辑 <input type="hidden" name="access_token" value="{{ token }}"/>
        # print(request.POST)
        # <QueryDict: {'access_token': ['{{ token }}'], 'pwd': [''],
        # 'csrfmiddlewaretoken': [''], 'sms_code': [''], 'mobile': [''], 'pic_code': ['']}>
        # print('3--',sign_openid)
        mobile = request.POST.get("mobile")
        pwd = request.POST.get("pwd")
        sms_code = request.POST.get("sms_code")

        # 2,校验参数
        # 2,1为空校验
        if not all([sign_openid, mobile, pwd, sms_code]):
            return http.HttpResponseForbidden("参数不全")

        # 2,2 校验sign_openid是否正确
        # openid 解密

        openid = decode_sign_openid(sign_openid)
        if not openid:
            return http.HttpResponseForbidden("openid过期")

        # 2,3 校验手机号的格式
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden("手机号格式有误")

        # 2,4 校验密码的格式
        if not re.match(r'^[0-9a-zA-Z]{8,20}$', pwd):
            return http.HttpResponseForbidden("密码格式有误")

        # 2,5 校验短信验证码的正确性
        redis_conn = get_redis_connection("code")
        redis_sms_code = redis_conn.get("sms_code_%s" % mobile)

        if not redis_sms_code:
            return http.HttpResponseForbidden("短信验证码已过期")

        if sms_code != redis_sms_code.decode():
            return http.HttpResponseForbidden("短信验证码填写错误")

        # 判断是否存在对应美多用户，若不存在则直接创建，并完成绑定
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 创建美多用户
            user = User.objects.create_user(username=mobile, mobile=mobile, password=pwd)

            # 创建绑定用户
            OAuthQQUser.objects.create(user=user, openid=openid)

            # 状态保持
            login(request, user)
            request.session.set_expiry(3600 * 24 * 2)

            # 返回到首页中
            response = redirect("/")
            response.set_cookie("username", user.username, max_age=3600 * 24 * 2)

            # 合并购物车
            response = merge_cookie_redis_cart(user, request, response)
            return response

        # 存在则直接绑定
        else:
            # 校验密码正确性
            if not user.check_password(pwd):
                return http.HttpResponseForbidden("密码错误")

            # 创建绑定用户
            OAuthQQUser.objects.create(user=user, openid=openid)

            # 状态保持
            login(request, user)
            request.session.set_expiry(3600 * 24 * 2)

            # 返回到首页中
            response = redirect("/")
            response.set_cookie("username", user.username, max_age=3600 * 24 * 2)

            # 合并购物车
            response = merge_cookie_redis_cart(user, request, response)
            return response

class OAuthWeiBoLoginView(View):
    def get(self, request):
        state = request.GET.get('next', '/')

        # 创建对象
        client = APIClient(
            app_key=settings.WEIBO_CLIENT_ID,
            app_secret=settings.WEIBO_CLIENT_SECRET,
            redirect_uri=settings.WEIBO_REDIRECT_URI)
        # 获取weibo登录页面
        login_url = client.get_authorize_url()
        # print(login_url)
        # 返回响应
        return http.JsonResponse({"login_url": login_url})

class SinaCallbackView(View):
    def get(self, request):
        # 1， 获取code
        state = request.GET.get('state')
        code = request.GET.get('code')

        # 判空
        if not code:
            return http.HttpResponseForbidden('code失效')

        return render(request, 'sina_callback.html')

class SinaUserView(View):
    def get(self,request):
        code = request.GET.get("code")
        state = request.GET.get('next', '/')

        # 判空
        if not code:
            return http.HttpResponseForbidden('code失效')

        # 创建client对象
        client_weibo = APIClient(
            app_key=settings.WEIBO_CLIENT_ID,
            app_secret=settings.WEIBO_CLIENT_SECRET,
            redirect_uri=settings.WEIBO_REDIRECT_URI)

        # 获取access_token & uid
        # uid用于用户绑定，access_token用于获取微博用户信息
        result = client_weibo.request_access_token(code)
        access_token = result.access_token
        uid = result.uid

        # 获取uid的关联用户
        try:
            oauth_weibo_user = OAuthSinaUser.objects.get(uid=uid)
        except OAuthSinaUser.DoesNotExist:
            # 初次授权
            # 将uid加密，并返回到页面渲染
            from oatuh.utils import generate_sign_openid
            sign_uid = generate_sign_openid(uid)
            # print('2--',sign_openid)

            # 组织数据
            context = {
                'access_token': sign_uid,
                'user_id':False,
            }
            return http.JsonResponse(context)

        # 非初次授权
        user = oauth_weibo_user.user
        # 状态保持
        login(request, user)
        request.session.set_expiry(3600 * 24 * 2)

        # 组织数据
        context = {
            "user_id":user.id,
            "username":user.username,
            "token":access_token,
        }
        # 返回响应
        # response = redirect('/')
        response = http.JsonResponse(context)
        response.set_cookie('username', user.username)

        # 合并购物车
        response = merge_cookie_redis_cart(user, request, response)
        return response

    def post(self,request):
        data = json.loads(request.body.decode())
        password = data.get("password")
        mobile = data.get("mobile")
        sms_code = data.get("sms_code")
        access_token = data.get("access_token")

        if not all([password, mobile, access_token, sms_code]):
            return http.HttpResponseForbidden("参数不全")

        # 2,2 校验sign_uid是否正确
        # sign_uid 解密

        token = decode_sign_openid(access_token)
        if not token:
            return http.HttpResponseForbidden("sign_uid过期")

        # 2,3 校验手机号的格式
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden("手机号格式有误")

        # 2,4 校验密码的格式
        if not re.match(r'^[0-9a-zA-Z]{8,20}$', password):
            return http.HttpResponseForbidden("密码格式有误")

        # 2,5 校验短信验证码的正确性
        redis_conn = get_redis_connection("code")
        redis_sms_code = redis_conn.get("sms_code_%s" % mobile)

        if not redis_sms_code:
            return http.HttpResponseForbidden("短信验证码已过期")

        if sms_code != redis_sms_code.decode():
            return http.JsonResponse({"status":'4001',"message":"验证码错误"})

        # 判断是否存在对应美多用户，若不存在则直接创建，并完成绑定
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 创建美多用户
            user = User.objects.create_user(username=mobile, mobile=mobile, password=password)

            # 创建绑定用户
            OAuthSinaUser.objects.create(user=user, uid=token)

            # 状态保持
            login(request, user)
            request.session.set_expiry(3600 * 24 * 2)

            # 组织数据
            context = {
                "user_id": user.id,
                "username": user.username,
                "token": token,
            }
            # 返回响应
            response = http.JsonResponse(context)

            response.set_cookie("username", user.username, max_age=3600 * 24 * 2)

            # 合并购物车
            response = merge_cookie_redis_cart(user, request, response)
            return response

        # 存在则直接绑定
        else:
            # 校验密码正确性
            if not user.check_password(password):
                return http.HttpResponseForbidden("密码错误")

            # 创建绑定用户
            OAuthSinaUser.objects.create(user=user, uid=token)

            # 状态保持
            login(request, user)
            request.session.set_expiry(3600 * 24 * 2)

            # 组织数据
            context = {
                "user_id": user.id,
                "username": user.username,
                "token": access_token,
            }
            # 返回响应
            response = http.JsonResponse(context)

            response.set_cookie("username", user.username, max_age=3600 * 24 * 2)

            # 合并购物车
            response = merge_cookie_redis_cart(user, request, response)
            return response




